#ifndef DATAKEYBOARD_H
#define DATAKEYBOARD_H

#include <QObject>
#include <QDebug>
#include <chrono>
#include "laserkeyboard.h"
#include "TouchManager.hpp"
#include "constants.h"

//#define RECORD_DATA
#define USE_GESTURE
#define USE_NEW_GESTURE
#define ONE_TIP_GATE 50
#define BG_BRIGHT_EPOCH 50
#define TRANS_CAM

#define cast_t(d) std::chrono::duration_cast<std::chrono::nanoseconds>(d).count()

class DataKeyboard : public LaserKeyboard
{
    Q_OBJECT
public:
    explicit DataKeyboard(LaserKeyboard *parent = nullptr);
    void run() override;



protected:
    void findTapPos(int CamIndex = 0) override;
    int handleImg(cv::Mat &src, double fps = 0) override;
    void writeIntoFile();
    void initFilePath();
    void updateTimeLine(const std::vector<int64>& timelines);
    void appendTimeLine(int64 time);
    void appendCurrentTime();
    void initTipsLine(int n);
    void appendTipsLine(int frame1, int frame2);
    void appendTipsPoints(int x, int y);
    void incVideoNum();
    void closeFile();
    bool judgeTap(const Contour & c, double area, const cv::Mat grayMat);

    bool inLeftRegion(cv::Point p);
    bool inRightRegion(cv::Point p);
    bool inInputRegion(cv::Point p);
    bool isDeleteKey(cv::Point p);

    //background avg brightness
    int bgBright;
    TouchManager touchManager;

#ifdef RECORD_DATA
    #define video_buffer_len 1000000
    cv::Mat videoBuffer[video_buffer_len];
    int64 videoFrameNum = 0;



    cv::Mat bufferMat = cv::Mat::zeros(CAM_HEIGHT, CAM_WIDTH, CV_8UC3);

    std::string dataDirPath = Constants::dataDirPath;

    std::string timeLineFilePath, tipslineFilePath, tipsPointsFilePath, videoPath, videoNumsPath;

    FILE *timelineFp = NULL, *tipslineFp = NULL, *tipsPointsFp = NULL, *videoNumsFp = NULL;

    cv::VideoWriter videowriter;

    double rate = 30;
    cv::Size frameSize = cv::Size(CAM_WIDTH, CAM_HEIGHT);
#endif

signals:
    void keyTapped(float, float);

    //a special gesture is triggered, index 1 for confirm, 2 for delete char, 3 for move left, 4 for move right
    void gestureTriggered(int);
public slots:
    void triggerKeyTappedSignal(float x,float y);
    void triggerGestureSignal(int k);
};

#define MOVE_GATE 50.0

#ifdef USE_NEW_GESTURE

class UpCallBack: public EventCallBack{
Q_OBJECT
public:

    void onSuccess(TouchEvent *event) override {
        TouchPoint point = ((TouchUp *)event)->getTouchPoint();
        Pos2F vec = getMoveVec(point);
        double moveDis = vec.x * vec.x + vec.y * vec.y;

        Pos2F pos = point.pos;
        auto nowC = std::chrono::high_resolution_clock::now();
        qDebug() << "Touch Up pos ( " << pos.x << ", " << pos.y << " ) move ( " << vec.x << " , " << vec.y << " ) dur: "
                 << cast_t(nowC - point.historyClocks.front()) / 1000000 << " , latest dur: " << cast_t(nowC - point.historyClocks.back()) / 1000000
                 << " ms";


        if(moveDis > MOVE_GATE) {
            qDebug() << " Gesture on";
            double xValue = abs(vec.x), yValue = abs(vec.y);
            if(xValue > yValue) {
                if(vec.x > 0) {
                    emit gestureSignal(4);
                }
                else  {
                    emit gestureSignal(3);
                }
            }
            else {
                if(vec.y < 0) {
                    emit gestureSignal(2);
                }
                else {
                    emit gestureSignal(1);
                }
            }
        }
        else {
            qDebug() << "point on";
            emit pointSignal((float)point.pos.x, (float)point.pos.y);
        }
        delete event;
        //qDebug() << "Touch Up move ( " << vec.x << " , " << vec.y << " ) \n";
    }



signals:
    void gestureSignal(int);
    void pointSignal(float, float);
};

#endif

class DownCallBack: public EventCallBack{

public:

    void onSuccess(TouchEvent *event) override {
        Pos2F pos = ((TouchDown *)event)->getPos();
        qDebug() << "Touch Down pos ( " << pos.x << " , " << pos.y << " ) \n";

        delete event;
    }
};

#endif // DATAKEYBOARD_H
